(ns ensemble.primary-stage
  (:import [javafx.scene DepthTest]
           [javafx.scene.control SelectionMode ToggleGroup ToolBar Control TreeItem]
           [javafx.scene.layout Pane VBox]
           [javafx.beans InvalidationListener]
           [javafx.scene.image ImageView]
           [javafx.application Platform]
           [javafx.stage Screen]
           [javafx.geometry Rectangle2D]
           [javafx.scene.input KeyEvent KeyCode])
  (:require [ensemble.primary-model :as model])
  (:use cljfx.dsl))

(defn gotoPage
  ([page] (gotoPage page true false true))
  ([page force] (gotoPage page true force true))
  ([page adHistory force swapViews]
    ))

(defn hideModalMessage [])
(defn back [])
(defn forward [])
(defn reload [])
(defn on-highlights-btn-clicked [])
(defn on-new-btn-clicked [])

(defn on-window-close [evt] (Platform/exit))
(defn on-window-min [evt]
  (.. evt getTarget getScene getWindow (setIconified true)))
(defn on-window-max [evt]
  (let [stage (.. evt getTarget getScene getWindow)
        screen (first (Screen/getScreensForRectangle (.getX stage) (.getY stage) 1 1))
        maximized model/maximized
        backup-window-bounds model/backup-window-bounds]
    (if @maximized
      (if @backup-window-bounds
        (doto stage
          (.setX (.getMinX @backup-window-bounds))
          (.setY (.getMinY @backup-window-bounds))
          (.setWidth (.getWidth @backup-window-bounds))
          (.setHeight (.getHeight @backup-window-bounds))))
      (do
        (reset! backup-window-bounds (Rectangle2D. (.getX stage) (.getY stage) (.getWidth stage) (.getHeight stage)))
        (doto stage
          (.setX (.. screen getVisualBounds getMinX))
          (.setY (.. screen getVisualBounds getMinY))
          (.setWidth (.. screen getVisualBounds getWidth))
          (.setHeight (.. screen getVisualBounds getHeight)))))
    (swap! maximized not)))

(declare toggle-btn-all toggle-btn-samples toggle-btn-docs pageTree pageToolBar text-box context-menu)

(defn on-clear-btn-clicked [evt]
  (doto text-box
    (.setText "")
    (.requestFocus)))
(defn on-text-box-key-released [evt]
  (if (= (.getCode evt) KeyCode/DOWN)
    (.requestFocus context-menu)))

(defn on-text-box-text-changed [observable old new])

(defn pageTreeToolBar []
  (proxy [ToolBar] []
    (requestLayout []
      (let [my-height (.getHeight this)]
        (proxy-super requestLayout)
        (and pageToolBar (not= my-height (.prefHeight pageToolBar -1))
          (.setPrefHeight pageToolBar my-height))))
    ))

(defn createTitleBtn [name]
  (button (text name)))

(defn add-sample-titles [page pane]
  (let [{direct-children :sample category-children :category} (group-by :type (:children page))]
    (.. pane getChildren (addAll (map #(createTitleBtn (:name %)) direct-children)))
    (doseq [category-child category-children] (add-sample-titles category-child pane))))

(defn createView [page]
  (let [{direct-children :sample category-children :category} (group-by :type (:children page))]
    (case (:type page)
      :category (scrollPane (styleClass "noborder-scroll-pane") (fitToWidth true)
                  (content
                    ((comp (spacing 8) (styleClass "category-page")
                       (children
                         (label (text (:name page)) (maxWidth Double/MAX_VALUE) (minHeight Control/USE_PREF_SIZE) (styleClass "page-header"))
                         (if (not-empty direct-children)
                           (tilePane (hgap 8) (vgap 8) (styleClass "category-page-flow")
                             (children (map #(createTitleBtn (:name %)) direct-children))))
                         (mapcat #([(label (text (:name %)) (maxWidth Double/MAX_VALUE) (minHeight Control/USE_PREF_SIZE) (styleClass "category-header"))
                                    (tilePane (hgap 8) (vgap 8) (prefColumns 1) (styleClass "category-page-flow")
                                      (partial add-sample-titles %))]) category-children))) (proxy [VBox] []
                                                                                              (computePrefHeight [this width]
                                                                                                (Math/max (proxy-super computePrefHeight width) (.. this getParent getBoundsInLocal getHeight))))))
                  ))))

(defn on-page-tree-selected-toggle-changed [this observable old new]
  (cond
    (= new toggle-btn-all) (.setRoot pageTree (TreeItem. model/root))
    (= new toggle-btn-samples) (.setRoot pageTree (TreeItem. model/samples))
    (= new toggle-btn-docs) (.setRoot pageTree (TreeItem. model/docs))
    ))

(defn rootComponent []
  (let [page-tree-toggle-group (toggleGroup (property-changed :selectedToggle on-page-tree-selected-toggle-changed))]
    (stackPane (depthTest DepthTest/DISABLE) ; layerPane
      (children
        (stackPane (id "ModalDimmer") (visible false)
          (on-mouse-clicked (fn [evt] (do (.consume evt) (hideModalMessage)))))
        (borderPane (id "root") (styleClass "application")
          (top (toolBar (id "mainToolBar") (prefHeight 66) (minHeight 66) (maxHeight 66) (gridpane-constraints 0 0)
                 (items
                   (ImageView. "images/logo.png") ;logo
                   (spacer)
                   (button (id "highlightsButton") (minSize 120 66) (prefSize 120 66) (on-action on-highlights-btn-clicked))
                   (button (id "newButton") (minSize 120 66) (prefSize 120 66) (on-action on-new-btn-clicked))
                   (spacer)
                   (ImageView. "images/search-text.png")
                   (pane (id "SearchBox") (minHeight 24) (prefSize 150 24) (maxHeight 24)
                     (children
                       (textField (promptText "Search")
                         (on-key-released on-text-box-key-released)
                         (property-changed :text on-text-box-text-changed) (defas text-box))
                       (button (visible false) (on-action on-clear-btn-clicked)))
                       (layoutChildren #(do
                                          (.resize text-box (.getWidth %) (.getHeight %))
                                          (.resizeRelocate clear-btn (- (.getWidth %) 18) 6 12 13)))
                     )
                   (vBox (spacing 8)
                     (children
                       (button (id "window-close") (on-action on-window-close))
                       (button (id "window-min") (on-action on-window-min))
                       (button (id "window-max") (on-action on-window-max)))))))
          (center (splitPane (id "page-splitpane") (maxSize Double/MAX_VALUE Double/MAX_VALUE) (dividerPosition 0 0.25)
                    (items
                      (borderPane ;leftSplitPane
                        (center (treeView (id "page-tree") (maxSize Double/MAX_VALUE Double/MAX_VALUE) (root (TreeItem. model/root))
                                  (showRoot false) (editable false) (selectionMode SelectionMode/SINGLE) (defas pageTree)
                                  ))
                        (top ((comp (id "page-tree-toolbar") (minHeight 29) (maxWidth Double/MAX_VALUE) ;pageTreeToolBar
                                (items
                                  (toggleButton (text "All") (in-toggle-group page-tree-toggle-group) (defas toggle-btn-all) (selected true))
                                  (toggleButton (text "Samples") (in-toggle-group page-tree-toggle-group) (defas toggle-btn-samples))
                                  (toggleButton (text "Document") (in-toggle-group page-tree-toggle-group) (defas toglge-btn-docs)))
                                ) (pageTreeToolBar)))
                        )
                      (borderPane ; rightSplitPane
                        (top (toolBar (id "page-toolbar") (minHeight 29) (maxSize Double/MAX_VALUE Double/MAX_VALUE) (defas pageToolBar)
                               (items
                                 (button (graphic (ImageView. "images/back.png")) (on-action back) (maxHeight Double/MAX_VALUE)) ;back button
                                 (button (graphic (ImageView. "images/forward.png")) (on-action forward) (maxHeight Double/MAX_VALUE)) ;forward button
                                 (button (graphic (ImageView. "images/reload.png")) (on-action reload) (maxHeight Double/MAX_VALUE))) ;reload button
                               ))
                        (center ((id "page-area") (proxy [Pane] []
                                                    (layoutChildren []
                                                      ))))
                        ))))
          )))))


